package com.spider.spiderflowable.core.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.spider.spiderflowable.business.entity.dto.ExecApprovalFlowInstParam;
import com.spider.spiderflowable.business.entity.param.ApprovalQueryParam;
import com.spider.spiderflowable.business.entity.vo.ProcessInstResultVo;
import com.spider.spiderflowable.common.CommonConstant;
import com.spider.spiderflowable.core.entity.dto.InstanceResultInfoData;
import com.spider.spiderflowable.core.entity.vo.FlowableTaskVO;
import com.spider.spiderflowable.core.service.SpiderTaskService;
import com.spider.spiderflowable.exception.BusinessException;
import com.spider.spiderflowable.utils.BeanUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.TaskService;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.identitylink.api.IdentityLink;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Map;

/**
 * @author xiong.bo
 * @version 1.0
 * @date 2024/5/7 8:18 下午
 */

@Slf4j
@Service
public class SpiderTaskServiceImpl implements SpiderTaskService {

  @Autowired
  private TaskService taskService;
  @Autowired
  private RepositoryService repositoryService;
  @Autowired
  private HistoryService historyService;


  @Override
  public void claim(String taskId, String userId) {
    taskService.claim(taskId, userId);
  }

  @Override
  public ProcessInstResultVo completeProcessInst(ExecApprovalFlowInstParam param) {
    if (ObjectUtil.isEmpty(param.getWorkFlowTaskId())) {
      throw new BusinessException("必填参数缺少,请检查参数");
    }
    ProcessInstResultVo resultVo = new ProcessInstResultVo();
    String taskId = param.getWorkFlowTaskId();
    Map<String, Object> parameter = param.getParameters();
    log.info("执行任务入参:taskId:{},variables:{}", taskId, JSON.toJSONString(parameter));
    Map<String, Object> executeTaskMap = this.complete(taskId, parameter, false);
    log.info("执行任务返回结果:{}", JSON.toJSONString(executeTaskMap));

    if (null != executeTaskMap) {
      InstanceResultInfoData finish = JSONUtil.toBean(
          (JSONObject) JSONUtil.parse(executeTaskMap.get("finish")), InstanceResultInfoData.class);
      List<InstanceResultInfoData> actives =
          JSONUtil.toList(
              JSONUtil.parseArray(executeTaskMap.get(CommonConstant.SIGNAL_ACTIVE_PLURAL)),
              InstanceResultInfoData.class);
      Boolean finishStatus = (Boolean) executeTaskMap.get("finishStatus");
      resultVo.setProcessIsFinish(finishStatus);
      resultVo.setActives(actives);
      resultVo.setFinish(finish);
    }
    return resultVo;
  }

  @Override
  public void delegateTask(String taskId, String userId) {
    taskService.delegateTask(taskId, taskId);
  }

  @Override
  public void setAssignee(String taskId, String userId) {
    taskService.setAssignee(taskId, userId);
  }

  @Override
  public boolean addTaskCandidateUser(String taskId, List<String> userIdList) {
    if (taskId != null && ObjectUtil.isNotEmpty(userIdList)) {
      userIdList.forEach(userId -> taskService.addCandidateUser(taskId, userId));
    }
    return true;
  }

  @Override
  public Map<String, Object> getVariables(String taskId) {
    return taskService.getVariables(taskId);
  }

  @Override
  public Page<FlowableTaskVO> queryTodoTask(String userId, ApprovalQueryParam param) {

    Page<FlowableTaskVO> result = new Page<>();

    Integer pageSize = param.getLimit();
    Integer pageNum = param.getPage();
    int firstResult = (pageNum - 1) * pageSize;

    List<Task> taskList = taskService.createTaskQuery()
        .taskCandidateOrAssigned(userId)
        .orderByTaskCreateTime().desc()
        .listPage(firstResult, pageSize);

    // 查询总条数（用于计算总页数）
    long total = taskService.createTaskQuery()
        .taskCandidateOrAssigned(userId)
        .count();

    List<FlowableTaskVO> taskVoList = BeanUtils.copyList(taskList, FlowableTaskVO.class);


    // 返回分页结果
    result.setTotal(total);
    result.setCurrent(pageNum);
    result.setSize(pageSize);
    result.setRecords(taskVoList);

    return result;
  }

  @Override
  public Page<FlowableTaskVO> queryDoneHisTask(String userId, ApprovalQueryParam param) {

    Page<FlowableTaskVO> result = new Page<>();

    Integer pageSize = param.getLimit();
    Integer pageNum = param.getPage();
    int firstResult = (pageNum - 1) * pageSize;

    // 计算总数
    long total = historyService.createHistoricTaskInstanceQuery()
        .taskAssignee(userId)
        .count();

    // 查询用户已办任务（历史任务）
    List<HistoricTaskInstance> historicTasks = historyService.createHistoricTaskInstanceQuery()
        .taskAssignee(userId)
        .orderByHistoricTaskInstanceEndTime().desc() // 按结束时间降序
        .listPage(firstResult, pageSize);

    List<FlowableTaskVO> taskVoList = BeanUtils.copyList(historicTasks, FlowableTaskVO.class);


    // 返回分页结果
    result.setTotal(total);
    result.setCurrent(pageNum);
    result.setSize(pageSize);
    result.setRecords(taskVoList);

    return result;
  }

  @Override
  public List<IdentityLink> getIdentityLinksForTask(String taskInstanceId) {
    // todo
    return null;
  }


  public Map<String, Object> complete(String taskId, Map<String, Object> variables,
      boolean localScope) {
    Map<String, Object> map = new HashMap<>(16);
    FlowableTaskVO finishTask;
    try {
      finishTask = queryTaskVOById(taskId);
    } catch (NullPointerException e) {
      throw new BusinessException(
          StrUtil.format(CommonConstant.WORKFLOW_TASK_ID_NOT_EXIST, taskId));
    }

    taskService.complete(taskId, variables, localScope);
    map.put("finish", finishTask);

    //当前结束的用户任务节点
    HistoricTaskInstance historicTask = historyService.createHistoricTaskInstanceQuery()
        .taskId(taskId).singleResult();

    List<Task> taskList = processInstanceId4Multi(finishTask.getProcessInstanceId());
    if (ObjectUtil.isEmpty(taskList)) {
      map.put("active", null);
      map.put("actives", null);
      map.put("finishStatus", true);
      return map;
    }
    map.put("finishStatus", false);//还有未完成的任务

    List<FlowableTaskVO> activeTaskList = BeanUtils.copyList(taskList, FlowableTaskVO.class);
    if (!ObjectUtil.isEmpty(finishTask)) {
      //只返回当前用户任务的下一个用户任务列表, 依据用户任务的创建时间,大于刚结束用户任务的结束时间。
      activeTaskList = activeTaskList.stream().filter(e ->
              e.getCreateTime().getTime() > historicTask.getEndTime().getTime())
          .collect(Collectors.toList());
      activeTaskList.forEach(e -> e.setProcessDefinitionKey(finishTask.getProcessDefinitionKey()));
    }
    if (!ObjectUtil.isEmpty(activeTaskList)) {
      map.put("active", activeTaskList.get(0));
      map.put("actives", activeTaskList);
    }
    return map;
  }


  public FlowableTaskVO queryTaskVOById(String taskId) {
    Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
    ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
        .processDefinitionId(task.getProcessDefinitionId()).singleResult();
    FlowableTaskVO taskVO = BeanUtils.copyBean(task, FlowableTaskVO.class);
    taskVO.setProcessDefinitionKey(processDefinition.getKey());
    return taskVO;
  }

  public List<Task> processInstanceId4Multi(String processInstanceId) {
    TaskQuery taskQuery = taskService.createTaskQuery().processInstanceId(processInstanceId)
        .active();
    return new ArrayList<>(taskQuery.list());
  }


}
